package com.umbacos.udm.client.model;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.umbacos.udm.client.arch.Popup;
import com.umbacos.udm.client.model.Files.SortOrder;

public class UdmStatus extends AsyncComm implements RequestCallback {

	public UdmStatus(){
		setCurDir("/");
	}
	
	public class Disk {
		public String available = "0";
		public String perc = "0%";
		public String size = "0";
		public String used = "0";
	}
	public class StandardResponse implements RequestCallback {

		@Override
		public void onError(Request request, Throwable exception) {
			Popup pp = new Popup("Error", new HTML(exception.getMessage()),
					Popup.POPUP_CLOSE);
			pp.showPopup();
		}

		@Override
		public void onResponseReceived(Request request, Response response) {
			Popup pp = new Popup("Server Response", new Label(response
					.getText()), Popup.POPUP_CLOSE);
			pp.showPopup();
			update(UPDATE_ALL);
		}
	}
	public interface UdmSubscriber {
		public void update();
	}

	public static final int UPDATE_ALL = 127;
	public static final int UPDATE_FILES = 1;
	public static final int UPDATE_TRACKERS = 2;
	public HashMap<String, String> amu = new HashMap<String, String>();

	private String curDir;
	public Disk disk = new Disk();
	public Files dnl = new Files();
	private ArrayList<UdmSubscriber> fileSubscribers = new ArrayList<UdmSubscriber>();
	public HashMap<String, String> nfo = new HashMap<String, String>();
	private ArrayList<UdmSubscriber> statSubscribers = new ArrayList<UdmSubscriber>();

	public HashMap<String, String> tor = new HashMap<String, String>();

	public String torrents = "0";

	private ArrayList<UdmSubscriber> trackerSubscribers = new ArrayList<UdmSubscriber>();

	public String wgets = "0";

	public HashMap<String, String> wgt = new HashMap<String, String>();

	public void addFileSubscription(UdmSubscriber fs) {
		fileSubscribers.add(fs);
	}

	public void addStatSubscription(UdmSubscriber fs) {
		statSubscribers.add(fs);
	}

	public void addTrackerSubscription(UdmSubscriber fs) {
		trackerSubscribers.add(fs);
	}

	public void clear() {
		torrents = "0";
		wgets = "0";
		disk = new Disk();
		nfo.clear();
		wgt.clear();
		tor.clear();
		amu.clear();
		dnl.clear();
		setCurDir("/");
		publish(statSubscribers);
		publish(trackerSubscribers);
	}

	public void clearFileSubscription() {
		fileSubscribers.clear();
	}

	public void clearStatSubscription() {
		statSubscribers.clear();
	}
	public void clearTrackerSubscription() {
		trackerSubscribers.clear();
	}
	public String getCurDir() {
		return curDir;
	}

	private boolean load(JSONObject jo, String what,
			HashMap<String, String> where) {

		try {
			JSONArray tmp = jo.get(what).isArray();
			String[] spli;
			where.clear();
			for (int i = 0; i < tmp.size(); ++i) {
				spli = tmp.get(i).isObject().get("obj").toString().replace(
						"\"", "").split("@");
				String pid = "";
				if (spli.length > 1)
					pid = spli[1];
				where.put(spli[0], pid);
			}
			return true;
		} catch (Exception e) {
		}
		return false;
	}

	public void onError(Request request, Throwable exception) {
		Popup pp = new Popup("Status Update", AsyncComm.SERVER_ERROR,
				Popup.POPUP_CLOSE);
		pp.show();
	}

	public void onResponseReceived(Request request, Response response) {
		if (200 == response.getStatusCode()) {
			try {
				JSONObject jo = new JSONObject(AsyncComm.JSON(response
						.getText()));
				populateThis(jo);
			} catch (Exception e) {
				Popup pp = new Popup("Status Update", new HTML(e.getMessage()),
						Popup.POPUP_CLOSE);
				pp.showPopup();
			}
			dnl.sortFiles(SortOrder.NAME);
		} else {
			Popup pp = new Popup("Status Update", new HTML(
					AsyncComm.SERVER_ERROR + "<br>" + response.getStatusCode()
							+ " " + response.getStatusText()),
					Popup.POPUP_CLOSE);
			pp.showPopup();
		}
	}

	private void populateThis(JSONObject jo) {

		boolean pubFiles = false;
		boolean pubTrack = false;

		torrents = jo.get("torrents").toString().replace("\"", "");
		wgets = jo.get("wgets").toString().replace("\"", "");
		disk.size = jo.get("disk").isObject().get("size").toString().replace(
				"\"", "");
		disk.available = jo.get("disk").isObject().get("available").toString()
				.replace("\"", "");
		disk.used = jo.get("disk").isObject().get("used").toString().replace(
				"\"", "");
		disk.perc = jo.get("disk").isObject().get("perc").toString().replace(
				"\"", "");

		pubTrack |= load(jo, "nfo", nfo);
		pubTrack |= load(jo, "wgt", wgt);
		pubTrack |= load(jo, "tor", tor);
		pubTrack |= load(jo, "amu", amu);

		try {
//			curDir = jo.get("curdir").toString().replace("\"", "");
			JSONArray jdnl = jo.get("dnl").isArray();
			JSONObject j;
			dnl.clear();
			for (int i = 0; i < jdnl.size(); ++i) {
				j = jdnl.get(i).isObject();
				File f = new File();
				f.file = j.get("file").toString().replace("\"", "");
				f.type = (j.get("type").toString().contains("d") ? File.FileType.DIR
						: File.FileType.FILE);
				f.inode = j.get("inode").toString().replace("\"", "");
				f.size = j.get("size").toString().replace("\"", "");
				f.date = j.get("date").toString().replace("\"", "");
				dnl.add(f);
			}
			pubFiles = true;
		} catch (Exception e) {
		}

		publish(statSubscribers);
		if (pubFiles)
			publish(fileSubscribers);
		if (pubTrack)
			publish(trackerSubscribers);
	}

	private void publish(ArrayList<UdmSubscriber> uss) {
		for (int i = 0; i < uss.size(); ++i)
			uss.get(i).update();
	}

	public void removeFileSubscription(UdmSubscriber fs) {
		fileSubscribers.remove(fs);
	}

	public void removeStatSubscription(UdmSubscriber fs) {
		statSubscribers.remove(fs);
	}

	public void removeTrackerSubscription(UdmSubscriber fs) {
		trackerSubscribers.remove(fs);
	}

	public void setCurDir(String path) {
		if (path.compareTo("..") == 0) {
			if (curDir.length() > 1)
				curDir = curDir.substring(0, curDir.lastIndexOf('/'));
				curDir = curDir.substring(0, curDir.lastIndexOf('/')) + "/";
		} else {
			if (path.charAt(0) != '/')
				curDir += "/" + path + "/";
			else
				curDir = path;
		}
		curDir = curDir.replaceAll("//", "/");
		
		Cookies.setCookie("curdir", URL.encode(curDir), new Date(System.currentTimeMillis()*2),"", "/udm/",false);

		update(UPDATE_FILES);
	}

	public final void standardRequest(String cmd, String file, String para) {
		AsyncComm ac = new AsyncComm();
		ac.addPostData("cmd", cmd);
		ac.addPostData("file", file);
		ac.addPostData("para", para);
		ac.send(AsyncComm.COMM, new StandardResponse());
	}

	public void update(int options) {
		AsyncComm ac = new AsyncComm();
		if ((options & UPDATE_FILES) == UPDATE_FILES)
			ac.addPostData("f", "1");
		if ((options & UPDATE_TRACKERS) == UPDATE_TRACKERS)
			ac.addPostData("t", "1");

		ac.send(AsyncComm.STAT, this);
	}
}
